# -*- coding: utf-8 -*-
# created on 2016/6/1


from mathsolver.functions.base import *
from sympy import Mul, fraction, Abs
from mathsolver.functions.sympy_utils import get_all_child, safe_degree
import random
from sympy.abc import x
from mathsolver.functions.root.jiefangchenzu import JieFangChenZu
from mathsolver.functions.root.jiefangchen import JieFangChen


# 含参一元一次方程无解问题
class YiCiWuJie(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        f = (f1 - f2).expand().simplify()
        symbol = default_symbol(f)
        assert f.is_Add
        a, h = f.as_independent(symbol)
        h = h.simplify()
        xishu = [arg for arg in h.args if not arg.has(symbol)]
        assert (len(xishu) > 0)
        coefficient = Mul._from_args(xishu)

        self.steps.append(["整理原方程, 得", self.output_eq([h.factor(), -a])])
        assert a != 0
        if a.is_Number:
            self.steps.append(["因为该方程无解，所以", self.output_eq([coefficient, 0])])
            self.output.append(BaseEq([coefficient, 0]))
        else:
            ineq = [[coefficient, 0], [a, "!=", 0]]
            self.steps.append(["因为该方程无解，所以", self.output_eqs(ineq)])
            self.output.append(base_gen(ineq))
        self.label.add("含参一元一次方程无解问题")
        return self


# 含参一元一次方程有唯一解问题
class YiCiWeiYiJie(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        f = (f1 - f2).expand().simplify()
        symbol = default_symbol(f)
        assert f.is_Add
        a, h = f.as_independent(symbol)
        h = h.simplify()

        self.steps.append(["整理原方程, 得", self.output_eq([h, -a])])
        xishu = [arg for arg in h.args if not arg.has(symbol)]
        assert (len(xishu) > 0)
        coefficient = Mul._from_args(xishu)
        self.steps.append(["因为该方程有唯一解，得", self.output_eq([coefficient, "\\neq", 0])])
        self.output.append(BaseIneq([coefficient, "\\neq", 0]))
        self.label.add("含参一元一次方程有唯一解问题")
        return self


# 含参一元一次方程有无数解问题
class YiCiWuShuJie(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        f = (f1 - f2).expand().simplify()
        symbol = default_symbol(f)
        assert f.is_Add
        a, h = f.as_independent(symbol)
        h = h.simplify()

        self.steps.append(["整理原方程, 得", self.output_eq([h, -a])])
        xishu = [arg for arg in h.args if not arg.has(symbol)]
        assert (len(xishu) > 0)
        coefficient = Mul._from_args(xishu)
        if a.is_Number:
            if a == 0:
                self.steps.append(["因为该方程有无数解，得", self.output_eq([coefficient, 0])])
                self.output.append(BaseEq([coefficient, 0]))
        else:
            eqs = [[coefficient.simplify(), 0], [-a, 0]]
            self.steps.append(["因为该方程有无数解，得", self.output_eqs(eqs)])
            self.output.append(BaseEqs(eqs))
        self.label.add("含参一元一次方程有无数解问题")
        return self


# 含参一元一次方程有解问题
class YiCiYouJie(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        f = (f1 - f2).expand().simplify()
        symbol = default_symbol(f)
        assert f.is_Add
        a, h = f.as_independent(symbol)
        h = h.simplify()

        self.steps.append(["整理原方程, 得", self.output_eq([h, -a])])
        xishu = [arg for arg in h.args if not arg.has(symbol)]
        assert (len(xishu) > 0)
        coefficient = Mul._from_args(xishu)

        self.steps.append(["", "因为该方程有解，存在两种情况：唯一解或无数解"])
        self.steps.append(["", "(1) 该方程有无数解，则"])
        if -a.is_Number:
            if -a == 0:
                self.steps.append(["", self.output_eq([coefficient, 0])])
                self.output.append(BaseEq([coefficient, 0]))
            else:
                self.steps.append(["", "因为%s \\neq 0, 该方程不存在无数解" % (new_latex(-a))])
        else:
            eqs = [[coefficient, 0], [-a, 0]]
            self.steps.append(["", self.output_eqs(eqs)])
            self.output.append(BaseEqs(eqs))
        self.steps.append(["", "(2) 该方程有唯一解，则"])
        ineq = [coefficient, "!=", 0]
        self.steps.append(["", self.output_eq(ineq)])
        self.output.append(BaseIneq(ineq))

        self.label.add("含参一元一次方程有解问题")
        return self


# 根据一元一次方程的定义求参
class YiCi005(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        f = f1 - f2
        if len(args) == 1:
            symbol = x
            target_symbol = list(f.free_symbols.difference([symbol]))
        else:
            if isinstance(args[1], BaseVariable):
                target_symbol = [args[1].sympify()]
            else:
                target_symbol = args[1].sympify()

            symbol = f.free_symbols.difference(target_symbol).pop()

        # x^(m+1)
        pow_args = get_all_child(f, lambda xx: xx.is_Pow and xx.args[0].has(symbol) and xx.args[1].has(*target_symbol))

        # (m+1)*x**2
        zero_exprs = get_all_child(f, lambda tt: tt.is_Mul and safe_degree(tt, symbol, 1) > 1)

        # (m+1)*x or (m+1)*x**(m-1)
        nonzero_exprs = get_all_child(f, lambda tt: tt.is_Mul and safe_degree(tt, symbol, 1) == 1)

        eqs = []
        for arg in pow_args:
            eqs.append([arg.args[1], S.One])

        for expr in zero_exprs:
            for arg in expr.args:
                if not arg.has(symbol) and arg.has(*target_symbol):
                    eqs.append([arg, S.Zero])

        for expr in nonzero_exprs:
            for arg in expr.args:
                if not arg.has(symbol) and arg.has(*target_symbol):
                    eqs.append([arg, "!=", S.Zero])

        if len(eqs) > 1:
            self.steps.append(["由一元一次方程的特点得", self.output_eqs(eqs)])
            self.output.append(base_gen(eqs))
        else:
            self.steps.append(["由一元一次方程的特点得", self.output_eq(eqs[0])])
            self.output.append(base_gen(eqs[0]))

        self.label.add("根据一元一次方程的定义，求参")

        # self.new_conditions = self.output
        # self.new_questions.append(BaseQuestion(args[1].value, "variable的值"))

        return self


# 一元一次方程的定义条件
class YiCiTiaoJian(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        f = f1 - f2
        if len(args) == 1:
            symbol = x
            target_symbol = list(f.free_symbols.difference([symbol]))
        else:
            if isinstance(args[1], BaseVariable):
                target_symbol = [args[1].sympify()]
            else:
                target_symbol = args[1].sympify()

            symbol = f.free_symbols.difference(target_symbol).pop()
        # x^(m+1)
        pow_args = get_all_child(f, lambda xx: xx.is_Pow and xx.args[0].has(symbol) and xx.args[1].has(*target_symbol))
        # (m+1)*x**2
        zero_exprs = get_all_child(f, lambda tt: tt.is_Mul and safe_degree(tt, symbol, 1) > 1)
        # (m+1)*x or (m+1)*x**(m-1)
        nonzero_exprs = get_all_child(f, lambda tt: tt.is_Mul and safe_degree(tt, symbol, 1) == 1)
        eqs = []
        for arg in pow_args:
            eqs.append([arg.args[1], S.One])
        for expr in zero_exprs:
            for arg in expr.args:
                if not arg.has(symbol) and arg.has(*target_symbol):
                    eqs.append([arg, S.Zero])
        for expr in nonzero_exprs:
            for arg in expr.args:
                if not arg.has(symbol) and arg.has(*target_symbol):
                    eqs.append([arg, "!=", S.Zero])
        if len(eqs) > 1:
            self.steps.append(["由一元一次方程的特点得", self.output_eqs(eqs)])
        else:
            self.steps.append(["由一元一次方程的特点得", self.output_eq(eqs[0])])
        self.label.add("一元一次方程的条件")
        return self


# 两一元一次方程同解问题
class YiCi006(BaseFunction):
    def solver(self, *args):
        eqs1 = args[0].sympify()
        eqs2 = args[1].sympify()
        f1 = (eqs1[0] - eqs1[1]).simplify()
        f2 = (eqs2[0] - eqs2[1]).simplify()
        f1_symbol = list(f1.free_symbols)
        f2_symbol = list(f2.free_symbols)
        if len(f1_symbol) == 2 and len(f2_symbol) == 2:
            self.steps.append(["", "关于方程%s与方程%s的解相同，得" % (self.output_eq(eqs1), self.output_eq(eqs2))])
            self.steps.append(["", self.output_eqs([eqs1, eqs2])])
            stepsolver = JieFangChenZu(verbose=True).solver(BaseEqs([eqs1, eqs2]))
            self.append(stepsolver)
            self.label.add("两一元一次方程同解问题：两方程都不可解")
        elif len(f1_symbol) == 1 or len(f2_symbol) == 1:
            self.steps.append(["", "依题意，得"])
            if len(f1_symbol) == 1:
                stepsolver = JieFangChen(verbose=True).solver(BaseEq(eqs1))
                self.append(stepsolver)
                jie = stepsolver.output[0].value
                a = jie.keys()[0]
                b = (jie[a])
                self.steps.append(["", "将%s = %s代入方程%s，得" % (new_latex(a), new_latex(b), self.output_eq(eqs2))])
                eq = f2.subs(a, b.args[0])
                self.steps.append(["", self.output_eq([eq, S.Zero])])
                self.output.append(BaseEq([eq, S.Zero]))
            elif len(f2_symbol) == 1:
                stepsolver = JieFangChen(verbose=True).solver(BaseEq(eqs2))
                self.append(stepsolver)
                jie = stepsolver.output[0].value
                a = jie.keys()[0]
                b = (jie[a])
                self.steps.append(["", "将%s = %s代入方程%s，得" % (new_latex(a), new_latex(b), self.output_eq(eqs1))])
                eq = f1.subs(a, b.args[0])
                self.steps.append(["", self.output_eq([eq, S.Zero])])
                self.output.append(BaseEq([eq, S.Zero]))
            self.label.add("两一元一次方程同解问题：有一方程可解")
        return self


def divisor(nn):
    divisor_number = [1]
    for xx in range(2, nn / 2 + 1):
        if nn % xx == 0:
            divisor_number.append(xx)
    divisor_number.append(nn)
    return divisor_number


class ZhengShuJieFangCheng(BaseFunction):
    def solver(self, *args):
        if isinstance(args[0], BaseSymbolValue):
            jies = args[0].sympify()
            root = jies[jies.keys()[0]].args[0]
        text = args[1]
        target = list(root.free_symbols)
        assert len(target) == 1
        answer = []
        if "正" in text:
            if root.is_Mul:
                if root.args[1].is_Pow and root.args[1].exp == -1 and root.args[0].is_Number:
                    self.steps.append(["", "因为解是正整数,得"])
                    fenzhi, fenmu = fraction(root)
                    if fenzhi.is_Integer:
                        yueshu_zheng = divisor(Abs(fenzhi))
                        if root.args[0] > 0:
                            for i, v in enumerate(yueshu_zheng, 1):
                                eq = [fenmu, v]
                                self.steps.append(["", "(%s) %s" % (new_latex(i), self.output_eq(eq))])
                                stepsolver = JieFangChen(verbose=True).solver(BaseEq(eq))
                                answer.append(stepsolver.output[0].value[stepsolver.output[0].value.keys()[0]].args[0])
                                solution = [stepsolver.output[0].value[stepsolver.output[0].value.keys()[0]].args[0]]
                                self.steps.append(["解得", self.output_jie(solution, target[0])])
                        elif root.args[0] < 0:
                            for i, v in enumerate(yueshu_zheng, 1):
                                eq = [fenmu, -v]
                                self.steps.append(["", "(%s) %s" % (new_latex(i), self.output_eq(eq))])
                                stepsolver = JieFangChen(verbose=True).solver(BaseEq(eq))
                                answer.append(stepsolver.output[0].value[stepsolver.output[0].value.keys()[0]].args[0])
                                solution = [stepsolver.output[0].value[stepsolver.output[0].value.keys()[0]].args[0]]
                                self.steps.append(["解得", self.output_jie(solution, target[0])])
        self.label.add("含参一元一次方程的解为正整数")
        self.output.append(BaseSymbolValue({target[0]: answer}))
        return self


# 构造一元一次方程
class YiCiGouZhao(BaseFunction):
    def solver(self, *args):
        if isinstance(args[0], BaseEq):
            eq = args[0].sympify()
        elif isinstance(args[0], BaseAny):
            answer = args[0].sympify()
            eq = [x, answer]
        elif isinstance(args[0], BaseSymbolValue):
            jies = args[0].sympify()
            root = jies[jies.keys()[0]].args[0]
            eq = [x, root]
        coff = random.randint(1, 100)
        self.steps.append(["", "把%s = %s的两边同时乘以%s, " % (new_latex(eq[0]), new_latex(eq[1]), new_latex(coff))])
        left = coff * eq[0]
        right = eq[1] * coff
        self.steps.append(["得", BaseEq([left, right]).printing()])
        return self


if __name__ == '__main__':
    pass
